<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <style>
      #canvas {
          background: #f1f1f1;
      }
  </style>
</head>
<body>
<input type="text" id="miterLimit" value="20"/>
<button id="button">点击生成</button>
<canvas id="canvas" width="300" height="300"></canvas>
<script>
    window.onload = () => {
        const canvas = document.getElementById('canvas')
        const ctx = canvas.getContext('2d')
        // 绘制矩形
        const drawFillStyle = () => {
            for (var i=0;i<6;i++){
                for (var j=0;j<6;j++){
                    ctx.fillStyle = 'rgb(' + Math.floor(255-42.5*i) + ',' +
                        Math.floor(255-42.5*j) + ',0)';
                    ctx.fillRect(j*25,i*25,25,25);
                }
            }
        }
        // drawFillStyle()

        const drawStrokeStyle = () => {
            for (var i=0;i<6;i++){
                for (var j=0;j<6;j++){
                    ctx.strokeStyle = 'rgb(' + Math.floor(255-42.5*i) + ',' +
                        Math.floor(255-42.5*j) + ',0)';
                    ctx.strokeRect(j*25,i*25,25,25);
                }
            }
        }
        // drawStrokeStyle()

        const drawGlobalAlpha = () => {
            // 画背景
            ctx.fillStyle = '#FD0';
            ctx.fillRect(0,0,75,75);
            ctx.fillStyle = '#6C0';
            ctx.fillRect(75,0,75,75);
            ctx.fillStyle = '#09F';
            ctx.fillRect(0,75,75,75);
            ctx.fillStyle = '#F30';
            ctx.fillRect(75,75,75,75);


            // 重新设置画布颜色为白色
            ctx.fillStyle = '#FFF';
            // 设置全局透明度值
            ctx.globalAlpha = 0.2;
            // 画半透明圆
            for (var i=0;i<7;i++){
                ctx.beginPath();
                ctx.arc(75,75,10+10*i,0,Math.PI*2,true);
                ctx.fill();
            }
        }
        // drawGlobalAlpha()

        const drawRgba = () => {
            var ctx = document.getElementById('canvas').getContext('2d');

            // 画背景
            ctx.fillStyle = 'rgb(255,221,0)';
            ctx.fillRect(0,0,150,37.5);
            ctx.fillStyle = 'rgb(102,204,0)';
            ctx.fillRect(0,37.5,150,37.5);
            ctx.fillStyle = 'rgb(0,153,255)';
            ctx.fillRect(0,75,150,37.5);
            ctx.fillStyle = 'rgb(255,51,0)';
            ctx.fillRect(0,112.5,150,37.5);

            // 画半透明矩形
            for (var i=0;i<10;i++){
                ctx.fillStyle = 'rgba(255,255,255,'+(i+1)/10+')';
                for (var j=0;j<4;j++){
                    ctx.fillRect(5+i*14,5+j*37.5,14,27.5)
                }
            }
        }
        // drawRgba()

        function drawLineWidth() {
            var ctx = document.getElementById('canvas').getContext('2d');
            for (var i = 0; i < 10; i++){
                ctx.lineWidth = 1+i;
                ctx.beginPath();
                ctx.moveTo(5+i*14,5);
                ctx.lineTo(5+i*14,140);
                ctx.stroke();
            }
        }
        // drawLineWidth()


        // 属性 lineCap 的值决定了线段端点显示的样子
        function drawLineCap() {
            var ctx = document.getElementById('canvas').getContext('2d');
            // 默认的 butt 。可以注意到它是与辅助线齐平的。中间的是 round 的效果，端点处加上了半径为一半线宽的半圆。
            // 右边的是 square 的效果，端点处加上了等宽且高度为一半线宽的方块。
            var lineCap = ['butt','round','square'];

            // 创建路径
            ctx.strokeStyle = '#09f';
            ctx.beginPath();
            ctx.moveTo(10,10);
            ctx.lineTo(140,10);
            ctx.moveTo(10,140);
            ctx.lineTo(140,140);
            ctx.stroke();

            // 画线条
            ctx.strokeStyle = 'black';
            for (var i=0;i<lineCap.length;i++){
                ctx.lineWidth = 15;
                ctx.lineCap = lineCap[i];
                ctx.beginPath();
                ctx.moveTo(25+i*50,10);
                ctx.lineTo(25+i*50,140);
                ctx.stroke();
            }
        }
        // drawLineCap()

        //lineJoin 的属性值决定了图形中两线段连接处所显示的样子
        function drawLineJoin() {
            var ctx = document.getElementById('canvas').getContext('2d');
            // round 的效果，边角处被磨圆了，圆的半径等于线宽。
            // 中间和最下面一条分别是 bevel 和 miter 的效果。
            // 当值是 miter 的时候，线段会在连接处外侧延伸直至交于一点，延伸效果受到下面将要介绍的 miterLimit 属性的制约。
            var lineJoin = ['round', 'bevel', 'miter'];
            ctx.lineWidth = 10;
            for (var i = 0; i < lineJoin.length; i++) {
                ctx.lineJoin = lineJoin[i];
                ctx.beginPath();
                ctx.moveTo(-5, 5 + i * 40);
                ctx.lineTo(35, 45 + i * 40);
                ctx.lineTo(75, 5 + i * 40);
                ctx.lineTo(115, 45 + i * 40);
                ctx.lineTo(155, 5 + i * 40);
                ctx.stroke();
            }
        }
        // drawLineJoin()

        // 就如上一个例子所见的应用 miter 的效果，线段的外侧边缘会被延伸交汇于一点上。
        // 线段之间夹角比较大时，交点不会太远，但随着夹角变小，交点距离会呈指数级增大
        // miterLimit 属性就是用来设定外延交点与连接点的最大距离，如果交点距离大于此值，连接效果会变成了 bevel
        function drawMiterLimit() {
            var ctx = document.getElementById('canvas').getContext('2d');

            // 清空画布
            ctx.clearRect(0, 0, 150, 150);

            // 绘制参考线
            ctx.strokeStyle = '#09f';
            ctx.lineWidth   = 2;
            ctx.strokeRect(-5, 50, 160, 50);

            // 设置线条样式
            ctx.strokeStyle = '#000';
            ctx.lineWidth = 10;

            // 检查输入
            if (document.getElementById('miterLimit').value.match(/\d+(\.\d+)?/)) {
                ctx.miterLimit = parseFloat(document.getElementById('miterLimit').value);
            } else {
                alert('Value must be a positive number');
            }

            // 绘制线条
            ctx.beginPath();
            ctx.moveTo(0, 100);
            for (i = 0; i < 24 ; i++) {
                var dy = i % 2 == 0 ? 25 : -25;
                ctx.lineTo(Math.pow(i, 1.5) * 2, 75 + dy);
            }
            ctx.stroke();
            return false;
        }
        document.getElementById('button').onclick = drawMiterLimit

        // 画虚线
        function drawDash() {
            var offset = 0;

            function draw() {
                ctx.clearRect(0,0, canvas.width, canvas.height);
                // setLineDash 方法接受一个数组，来指定线段长度，以及间隙的宽度
                ctx.setLineDash([10, 5]);
                // lineDashOffset 属性设置起始偏移量
                ctx.lineDashOffset = -offset;
                ctx.strokeRect(10,10, 100, 100);
            }

            function march() {
                offset++;
                if (offset > 16) {
                    offset = 0;
                }
                draw();
                // 重复执行，设置不同的其实偏移量，
                setTimeout(march, 20);
            }

            march();
        }
        // drawDash()

        // 线性渐变的效果
        function drawLinearGradient() {
            var ctx = document.getElementById('canvas').getContext('2d');

            // createLinearGradient 方法接受 4 个参数，表示渐变的起点 (x1,y1) 与终点 (x2,y2)。
            var lingrad = ctx.createLinearGradient(0,0,0,150);

            //  addColorStop 方法接受 2 个参数，position 参数必须是一个 0.0 与 1.0 之间的数值，表示渐变中颜色所在的相对位置。
            //  例如，0.5 表示颜色会出现在正中间。color 参数必须是一个有效的 CSS 颜色值（如 #FFF， rgba(0,0,0,1)，等等）。
            lingrad.addColorStop(0, '#00ABEB');
            lingrad.addColorStop(0.5,'#26C000');
            lingrad.addColorStop(1, '#fff');
            ctx.fillStyle = lingrad;
            ctx.fillRect(10,10,130,130);

            var lingrad2 = ctx.createLinearGradient(0,50,0,95);
            lingrad2.addColorStop(0.5, '#000');
            lingrad2.addColorStop(1, 'rgba(0,0,0,0)');
            ctx.strokeStyle = lingrad2;
            ctx.strokeRect(50,50,50,50);

        }
        drawLinearGradient()


        // 径向渐变
        function drawRadialGradient() {
            var ctx = document.getElementById('canvas').getContext('2d');

            // 创建渐变
            // createRadialGradient(x1, y1, r1, x2, y2, r2)
            // createRadialGradient 方法接受 6 个参数，前三个定义一个以 (x1,y1) 为原点，半径为 r1 的圆，后三个参数则定义另一个以 (x2,y2) 为原点，半径为 r2 的圆。
            var radgrad = ctx.createRadialGradient(45,45,10,52,50,30);
            radgrad.addColorStop(0, '#A7D30C');
            radgrad.addColorStop(0.5, '#019F62');
            radgrad.addColorStop(1, 'rgba(1,159,98,0.1)');

            var radgrad2 = ctx.createRadialGradient(105,105,20,112,120,50);
            radgrad2.addColorStop(0, '#FF5F98');
            radgrad2.addColorStop(0.75, '#FF0188');
            radgrad2.addColorStop(1, 'rgba(255,1,136,0.1)');

            var radgrad3 = ctx.createRadialGradient(95,15,15,102,20,40);
            radgrad3.addColorStop(0, '#00C9FF');
            radgrad3.addColorStop(0.8, '#00B5E2');
            radgrad3.addColorStop(1, 'rgba(0,201,255,0.1)');

            var radgrad4 = ctx.createRadialGradient(0,150,50,0,140,90);
            radgrad4.addColorStop(0, '#F4F201');
            radgrad4.addColorStop(0.8, '#E4C700');
            radgrad4.addColorStop(1, 'rgba(228,199,0,0.1)');

            // 画图形
            ctx.fillStyle = radgrad;
            ctx.fillRect(0,0,150,150);
            ctx.fillStyle = radgrad3;
            ctx.fillRect(0,0,150,150);
            ctx.fillStyle = radgrad2;
            ctx.fillRect(0,0,150,150);
            ctx.fillStyle = radgrad;
            ctx.fillRect(0,0,150,150);
        }
        // drawRadialGradient()


        // 创建重复图案
        function drawCreatePattern() {
            var ctx = document.getElementById('canvas').getContext('2d');

            // 创建新 image 对象，用作图案
            var img = new Image();
            img.src = 'https://mdn.mozillademos.org/files/222/Canvas_createpattern.png';
            img.onload = function() {

                // 创建图案
                // createPattern(image, type)
                // 该方法接受两个参数。Image 可以是一个 Image 对象的引用，或者另一个 canvas 对象。
                // Type 必须是下面的字符串值之一：repeat，repeat-x，repeat-y 和 no-repeat。
                var ptrn = ctx.createPattern(img, 'repeat');
                ctx.fillStyle = ptrn;
                ctx.fillRect(0, 0, 150, 150);

            }
        }
        // drawCreatePattern()



        //  文字阴影
        function drawTextShadow() {
            var ctx = document.getElementById('canvas').getContext('2d');

            ctx.shadowOffsetX = 2;
            ctx.shadowOffsetY = 2;
            ctx.shadowBlur = 2;
            ctx.shadowColor = "rgba(0, 0, 0, 0.5)";

            ctx.font = "20px Times New Roman";
            ctx.fillStyle = "Black";
            ctx.fillText("HElloworld", 5, 30);

            ctx.fillStyle = "red";
            ctx.fillText("Sample String", 30, 50);
        }

        drawTextShadow()


        // 填充规则
        // 当我们用到 fill（或者 clip和isPointinPath ）你可以选择一个填充规则，
        // 该填充规则根据某处在路径的外面或者里面来决定该处是否被填充，这对于自己与自己路径相交或者路径被嵌套的时候是有用的。
        function drawFill() {
            var ctx = document.getElementById('canvas').getContext('2d');
            ctx.beginPath();
            ctx.arc(50, 50, 50, 0, Math.PI*2, true);
            ctx.arc(50, 50, 30, 0, Math.PI*2, true);
            ctx.arc(50, 50, 15, 0, Math.PI*2, true);
            ctx.fillStyle = 'red'
            ctx.fill('evenodd'); // nonzero 默认值  / evenodd 最外层一定填充，如果有倒数第二层，则不填充，以此往复
        }
        // drawFill()
    }




</script>
</body>
</html>
